#include "hzpch.h"
#include "Shader.h"
#include "SourceCode/Renderer/Renderer.h"
#include "SourceCode/Platforms/OpenGL/OpenGLShader.h"

namespace Hazal
{
	Ref<CShader> CShader::Create(const std::string& strShaderName, const std::string& strVertexSrc, const std::string& strFragmentSrc)
	{
		switch (CRenderer::GetAPI())
		{
		case CRendererAPI::API::None:
		{
			HZ_ASSERT(false, "RendererAPI::None is not supported!");
			return nullptr;
		}
		case CRendererAPI::API::OpenGL:
		{
			return std::make_shared<COpenGLShader>(strShaderName, strVertexSrc, strFragmentSrc);
		}
		break;
		default:
			break;
		}

		HZ_ASSERT(false, "No renderer API is supported!");
		return nullptr;
	}

	Ref<CShader> CShader::Create(const std::string& strShaderPath)
	{
		switch (CRenderer::GetAPI())
		{
		case CRendererAPI::API::None:
		{
			HZ_ASSERT(false, "RendererAPI::None is not supported!");
			return nullptr;
		}
		case CRendererAPI::API::OpenGL:
		{
			return std::make_shared<COpenGLShader>(strShaderPath);
		}
		break;
		default:
			break;
		}

		HZ_ASSERT(false, "No renderer API is supported!");
		return nullptr;
	}

	////////////////// CShaderLibrary //////////////////////////
	void CShaderLibrary::Add(const std::string strShaderName, const Ref<CShader>& pShader)
	{
		HZ_CORE_ASSERT(!Exists(strShaderName), "Current shader has already exists!");
		m_mapShaders[strShaderName] = pShader;
	}

	void CShaderLibrary::Add(const Ref<CShader>& pShader)
	{
		const std::string& strShaderName = pShader->GetName();
		Add(strShaderName, pShader);
	}

	Ref<CShader> CShaderLibrary::Load(const std::string& strShaderFilePath)
	{
		Ref<CShader> pShader = CShader::Create(strShaderFilePath);

		Add(pShader);

		return pShader;
	}

	Ref<CShader> CShaderLibrary::Load(const std::string& strShaderName, const std::string& strShaderFilePath)
	{
		Ref<CShader> pShader = CShader::Create(strShaderFilePath);

		Add(strShaderName, pShader);

		return pShader;
	}

	Ref<CShader> CShaderLibrary::Get(const std::string& strShaderName)
	{
		if (Exists(strShaderName))
		{
			return m_mapShaders[strShaderName];
		}
		else
		{
			LOG_CORE_ERROR("Shader({0}) is not exist!", strShaderName.c_str());
			return nullptr;
		}

		return nullptr;
	}

	bool CShaderLibrary::Exists(const std::string& strShaderName) const
	{
		return m_mapShaders.find(strShaderName) != m_mapShaders.end();
	}
}